package edu.cmu.arch.pipesandfilters;

import edu.cmu.arch.pipesandfilters.frame.Variable;

import java.io.File;
import java.io.IOException;
import java.util.*;

/**
* File:SystemC.java
* Course: 17655
* Project: Assignment 1
* Group: Group 1
* @author Michael Azzopardi
* Versions:
*	1.0 February 2012
*
* This is the main program for the implementation of the Pipe-and-Filter network for System C
* 
*/
public class SystemC {

	/**
	 * @param args
	 * @author Michael Azzopardi
	 * 
	 */
	public static void main(String[] args) {
		System.out.println("Initializing System C Pipe-and-Filter Network");
		System.out.println("developed by Group 1");
		System.out.println("=============================================");		
		try {
			// Define file names	
			String sourceFilenameA = "DataSets" + File.separator + "SubSetA.dat";
			String sourceFilenameB = "DataSets" + File.separator + "SubSetB.dat";
			String outputFilename = "DataSets" + File.separator + "OutputC.dat";
			String wildOutputFilenameA = "DataSets" + File.separator + "RejectData1.dat";
			String wildOutputFilenameB = "DataSets" + File.separator + "RejectData2.dat";
			
			if (args.length > 0) {
				if (args[0] != null) {
					sourceFilenameA = args[0];
				} else {
					System.out.println("Missing input filename parameter");
				}
				
				if (args[1] != null) {
					sourceFilenameB = args[1];
				} else {
					System.out.println("Missing input 2 filename parameter");
				}
				
				if (args[2] != null) {
					outputFilename = args[2];
				} else {
					System.out.println("Missing output filename parameter");
				}
			
				if (args[3] != null) {
					wildOutputFilenameA = args[3];
				} else {
					System.out.println("Missing wildpoint output filename A parameter");
				}
				
				if (args[4] != null) {
					wildOutputFilenameB = args[4];
				} else {
					System.out.println("Missing wildpoint output filename B parameter");
				}
						
			}
			System.out.println("Starting System C with input "+ sourceFilenameA + "and " + sourceFilenameB +" and output " + outputFilename + " and wildpoint output " + wildOutputFilenameA + "and " + wildOutputFilenameB);
			
			
			// DefineFilters
			SourceFilter sourceFilterA;
			SourceFilter sourceFilterB;			
			StripFilter stripFilterA;
			StripFilter stripFilterB;
			ConversionFilter tempConversionFilterA;
			ConversionFilter altConversionFilterA;
			ConversionFilter tempConversionFilterB;
			ConversionFilter altConversionFilterB;
			TimeSequentialMergeFilter mergeFilter;
			ExtrapolateFilter extrapolateFilter;
			RangeFilter rangeFilter;
			StripFilter wildpointStripFilterA;
			StripFilter wildpointStripFilterB;	
			StripFilter outputStripFilter;
			FileSinkFilter sinkFilter;
			FileSinkFilter wildpointSinkFilterA;
			FileSinkFilter wildpointSinkFilterB;
			ArrayList<Variable> stripMeasurements;				
			ArrayList<Variable> wildPointsMeasurementsA;
			ArrayList<Variable> wildPointsMeasurementsB;
			ArrayList<Variable> outputMeasurements;
			// Instantiate sourceFilter
			sourceFilterA = new SourceFilter();
			sourceFilterB = new SourceFilter();
			
			// Set fileName for sourceFilter
			sourceFilterA.setFileName(sourceFilenameA);
			sourceFilterB.setFileName(sourceFilenameB);
	
			// Instantiate filters
			stripMeasurements = new ArrayList<Variable>();
			stripMeasurements.add(Variable.Time);
			stripMeasurements.add(Variable.Temperature);
			stripMeasurements.add(Variable.Altitude);
			stripMeasurements.add(Variable.Pressure);
			stripMeasurements.add(Variable.Attitude);
			stripFilterA = new StripFilter(stripMeasurements);
			stripFilterB= new StripFilter(stripMeasurements);
			
			tempConversionFilterA = new ConversionFilter(Variable.Temperature);
			altConversionFilterA = new ConversionFilter(Variable.Altitude);		
			tempConversionFilterB = new ConversionFilter(Variable.Temperature);
			altConversionFilterB = new ConversionFilter(Variable.Altitude);		
			
			mergeFilter = new TimeSequentialMergeFilter();
			extrapolateFilter = new ExtrapolateFilter(Variable.Pressure,45D,90D);
			
			rangeFilter = new RangeFilter(Variable.Attitude, 10D, Variable.Pressure, 65D);
			
			wildPointsMeasurementsA =new ArrayList<Variable>();
			wildPointsMeasurementsA.add(Variable.Time);
			wildPointsMeasurementsA.add(Variable.Pressure);		
			wildpointStripFilterA = new StripFilter(wildPointsMeasurementsA);
			
			wildPointsMeasurementsB = new ArrayList<Variable>();
			wildPointsMeasurementsB.add(Variable.Time);			
			wildPointsMeasurementsB.add(Variable.Attitude);
			wildPointsMeasurementsB.add(Variable.Pressure);			
			wildpointStripFilterB = new StripFilter(wildPointsMeasurementsB);		
			
			outputMeasurements = new ArrayList<Variable>();
			outputMeasurements.add(Variable.Time);
			outputMeasurements.add(Variable.Temperature);
			outputMeasurements.add(Variable.Altitude);
			outputMeasurements.add(Variable.Pressure);	
			outputMeasurements.add(Variable.ExtrapolatedId);
			outputStripFilter = new StripFilter(outputMeasurements);
			
			
		
			// Initialize and set fileName, header and separator for sinkFilter
			sinkFilter = new FileSinkFilter(outputMeasurements, outputFilename);
			wildpointSinkFilterA = new FileSinkFilter(wildPointsMeasurementsA, wildOutputFilenameA);
			wildpointSinkFilterB	= new FileSinkFilter(wildPointsMeasurementsB, wildOutputFilenameB);
			
			// Connect filters
			stripFilterA.Connect(sourceFilterA);
			stripFilterB.Connect(sourceFilterB);
			tempConversionFilterA.Connect(stripFilterA);
			altConversionFilterA.Connect(tempConversionFilterA);
			tempConversionFilterB.Connect(stripFilterB);
			altConversionFilterB.Connect(tempConversionFilterB);
			
			mergeFilter.Connect(altConversionFilterA, altConversionFilterB);
			extrapolateFilter.Connect(mergeFilter);
			wildpointStripFilterA.Connect(extrapolateFilter.getOutputFilter2());
			rangeFilter.Connect(extrapolateFilter.getOutputFilter1());
			wildpointStripFilterB.Connect(rangeFilter.getOutputFilter2());
			outputStripFilter.Connect(rangeFilter);
			sinkFilter.Connect(outputStripFilter);
			wildpointSinkFilterA.Connect(wildpointStripFilterA);
			wildpointSinkFilterB.Connect(wildpointStripFilterB);
			
			
			// Start filters
			sourceFilterA.start();
			sourceFilterB.start();			
			stripFilterA.start();
			stripFilterB.start();
			tempConversionFilterA.start();
			altConversionFilterA.start();
			tempConversionFilterB.start();
			altConversionFilterB.start();
			mergeFilter.start();
			extrapolateFilter.start();
			rangeFilter.start();
			wildpointStripFilterA.start();
			wildpointStripFilterB.start();	
			outputStripFilter.start();
			sinkFilter.start();
			wildpointSinkFilterA.start();
			wildpointSinkFilterB.start();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("Error : "+e.getMessage());
			e.printStackTrace();
		}			
	}

}

		
